package com.alibaba.algo.components.yapi.handler;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import com.alibaba.algo.components.yapi.entity.Mock;
import com.alibaba.algo.components.yapi.entity.Node;
import com.alibaba.algo.components.yapi.entity.YapiProperty;
import com.alibaba.algo.components.yapi.util.ClazzUtils;
import com.alibaba.algo.components.yapi.util.TypeConverter;
import com.alibaba.fastjson.JSON;

import lombok.extern.slf4j.Slf4j;

/**
 * @Description: yapi 返回值handler处理类
 * @author: malin
 * @date: 2020-12-4 10:53:21
 */
@Slf4j
@Component
public class ResponseHandler {

	public String handler(Class<?> responseModel, boolean isPaged, boolean isList) {
		log.info("responseModel:{}", responseModel.getName());
		Map<String, Object> result = new LinkedHashMap<String, Object>();
		List<String> required = new ArrayList<String>();
		Map<String, Object> properties = new LinkedHashMap<String, Object>();
		result.put("required", required);
		result.put("type", "object");
		result.put("properties", properties);
		properties.put("code", new YapiProperty("integer", "状态码", new Mock("0")));
		properties.put("message", new YapiProperty("string", "错误信息", null));
		required.add("code");
		required.add("message");

		if (responseModel == Void.class) {
			return JSON.toJSONString(result);
		}
		if (ClazzUtils.simpleClass(responseModel)) {
			// 判断这个类是否是常用类型
			properties.put("data",
					new YapiProperty(TypeConverter.getYapiType(responseModel.getTypeName()), "返回内容", null));
			required.add("data");
		} else {
			Map<String, Object> data = new LinkedHashMap<String, Object>();
			Map<String, Object> dataProperties = new LinkedHashMap<String, Object>();
			List<String> dataRequired = new ArrayList<String>();
			data.put("required", dataRequired);
			data.put("properties", dataProperties);
			data.put("type", "object");
			// 分页情况 说明返回值为PagerEntity 里面泛型为responseModel类
			if (isPaged) {
				dataProperties.put("total", new YapiProperty("integer", "总条数", new Mock("26")));
				dataProperties.put("totalPages", new YapiProperty("integer", "总页数", new Mock("2")));
				dataProperties.put("pageIndex", new YapiProperty("integer", "页码", new Mock("1")));
				dataProperties.put("pageSize", new YapiProperty("integer", "页容量", new Mock("20")));
				dataRequired.addAll(new ArrayList<String>() {
					{
						add("total");
						add("totalPages");
						add("pageIndex");
						add("pageSize");
					}
				});
				required.addAll(dataRequired);
			}
			List<Node> nodeList = ClazzUtils.getChildrenNodes(responseModel, new LinkedHashMap<String, String>());
			if (CollectionUtils.isEmpty(nodeList)) {
				return JSON.toJSONString(result);
			}
			log.info("nodeList:{}", JSON.toJSONString(nodeList));
			if (!CollectionUtils.isEmpty(nodeList)) {
				if (nodeList.size() == 1) {
					data.put("type", nodeList.get(0).getType());
				} else {
					data.put("type", "object");
				}
				required.add("data");
				Set<String> allRequired = new HashSet<String>();
				Map<String, Object> readResult = ClazzUtils.read(nodeList, new LinkedHashMap<String, Object>(),
						allRequired);
				if (isPaged) {
					Map<String, Object> dataList = new LinkedHashMap<String, Object>();
					Map<String, Object> itemMap = new LinkedHashMap<String, Object>(4);
					dataList.put("type", "array");
					dataList.put("items", itemMap);
					itemMap.put("type", "object");
					itemMap.put("properties", readResult.get("properties"));
					if (readResult.get("required") != null) {
						itemMap.put("required", readResult.get("required"));
					}
					dataProperties.put("dataList", dataList);
					dataRequired.add("dataList");
				} else if (isList) {
					data.put("type", "array");
					Map<String, Object> itemMap = new LinkedHashMap<String, Object>(3);
					data.put("items", itemMap);
					itemMap.put("type", "object");
					itemMap.put("properties", readResult.get("properties"));
					if (readResult.get("required") != null) {
						itemMap.put("required", readResult.get("required"));
					}
				} else {
					data.put("properties", readResult.get("properties"));
				}
				if (!CollectionUtils.isEmpty(allRequired)) {
					dataRequired.addAll(allRequired);
					required.addAll(new HashSet<String>(allRequired));
				}
				properties.put("data", data);
			}
		}
		return JSON.toJSONString(result);
	}
}
